﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

namespace daStaticAnalyser.Analysers
{
    using daStaticAnalyser;
    using daBase.Objects;
    using daBase.Analyser;
    using daSyntaxAnalyser;
    using daSyntaxAnalyser.SyntaxTree;

    [AnalyserDefaultSettings("Метрика Чепина", "test", 0, "test")]
    class ChepinAnalyzer : BaseStaticAnalyser
    {
        private void GetData(ISyntaxTreeElement Element, bool InControlOperator)
        {
            if (Element == null)
                return;

            if (Element is StandartVariableExpressionElement)
            {
                String temp = Element.ToString();
                if (!temp.Contains("("))
                {
                    String[] strs = temp.Split('.');
                    if (InControlOperator)
                    {
                        if (!ControlVars.Contains(strs[0])) ControlVars.Add(strs[0]);    
                    }
                    else
                    {
                        if (GlobalVar.Contains(strs[0]) || IOVars.Contains(strs[0]) || MethodVars.Contains(strs[0]))
                        {
                            if (!UsingVars.Contains(strs[0])) UsingVars.Add(strs[0]);
                        }
                    }
                }
            }
            else if (Element is TestStatementElement)
            { 
                GetData((Element as TestStatementElement).Test, true);
            }
            else if (Element is CaseStatementElement)
            {
                GetData((Element as CaseStatementElement).Expression, true);
            }
            else if (Element is ForStatementElement)
            {
                GetData((Element as ForStatementElement).End, true);
            }
            else if (Element is WhileStatementElement)
            {
                GetData((Element as WhileStatementElement).Condition, true);
            }
            else if (Element is RepeatStatementElement)
            {
                GetData((Element as RepeatStatementElement).Condition, true);
            }            

            foreach (ISyntaxTreeElement element in Element)
            {
                GetData(element, InControlOperator);
            }
        }

        List<String> UsingVars,//Переменные, используемые в подпрограмме 
                     ControlVars,//Управляющие переменные
                     MethodVars,//Переменные, объявленные в подпрограмме
                     IOVars;//Переменные вводимые для расчётов и обеспечения вывода
        protected override void DoAnalyse(SyntaxTreeArgs e)
        {
            String MethodName = "";
            if (CheckMethod_GetName(e, out MethodName))
            {
                OuterMethodElement Method = e.Element as OuterMethodElement;

                MethodVars = new List<string>();
                IOVars = new List<string>();
                List<String> ParazitVars = new List<string>();

                if ((Method.Header is InnerProcedureHeadElement) || (Method.Header is ProcedureTypeElement))
                {
                    List<FunctionVarDeclarationElement> vars;
                    vars = (Method.Header is InnerProcedureHeadElement) ? (Method.Header as InnerProcedureHeadElement).Vars : vars = (Method.Header as ProcedureTypeElement).Vars;
                    if (vars != null)
                    {
                        foreach (FunctionVarDeclarationElement declaration in vars)
                        {
                            foreach (IdElement id in declaration.Ids) IOVars.Add(id.ToString());
                        }
                    }
                }                
                
                foreach (var vars in Method.Body.Declarations)
                {
                    if (vars is VarDeclarationsElement)
                    {
                        foreach (var v in (vars as VarDeclarationsElement).Vars)
                        {
                            VarDeclarationElement vardec = v as VarDeclarationElement;
                            foreach (IdElement id in vardec.Ids) MethodVars.Add(id.ToString());
                        }
                    }
                }

                UsingVars = new List<string>();
                ControlVars = new List<string>();
                GetData((e.Element as OuterMethodElement).Body, false);

                foreach (String var in MethodVars)
                {
                    if (!UsingVars.Contains(var)) ParazitVars.Add(var);
                }

                int P = IOVars.Count;
                int M = MethodVars.Count;
                int C = ControlVars.Count;
                int T = ParazitVars.Count;

                float Q = P + 2*M + 3*C + Convert.ToSingle(0.5*T);

                AddMetric("Метрика Чепина",
                            Q,
                            MethodName,
                            e.Element.StartInfo.File,
                            e.Element.StartInfo.Line);
            }
            else
            {
                GlobalVarFind(e.Element);
            }
        }

        protected override void DoFinishAnalyse(EventArgs e)
        {
            GlobalVar.Clear();
        }
    }
}
